import os
import win32gui
import Levenshtein
from PySide6.QtCore import Qt, QSize, QPoint
from PySide6.QtWidgets import  QWidget, QHBoxLayout, QVBoxLayout, QListWidgetItem, QTextEdit
from qfluentwidgets import SingleDirectionScrollArea, SimpleCardWidget, CaptionLabel, ListWidget, LineEdit, ComboBox, PushButton

from core.maocr import maocr
from core.log import logger
from core.mhdt import dt_nav
from gui.qalabel import QALabel
from core.screenshot import hwnd_title, get_all_hwnd, get_screenshot_image, get_mss_screenshot_image
from core.util import time_str, delete_file
import core.model_signin as u
from gui.common_gui import GUI_CARD
from gui.gui_developmode import SFormDevelopMode
import setting as c

def custom_sort(item, text):
    return Levenshtein.distance(item[1], text)

class QaInfoCard(SimpleCardWidget):
    """ App information card """

    def __init__(self, parent=None):
        super().__init__(parent)
        
        self.father = parent
        self.card = GUI_CARD.QA
        self.sf_developmode = SFormDevelopMode(self, "QA截图校准", self.card, 0)
        self.sf_developmode.setModal(True)
        
        self.alert_lb = CaptionLabel()
        self.alert_lb.setText(c.TIPS_QA_ALERT)
        self.alert_lb.setOpenExternalLinks(True)
       
        self.win_nav = ComboBox()
        self.win_nav_sub = ComboBox()
        for n in dt_nav:
            self.win_nav.addItem(n[0])
        for ns in dt_nav[0][1]:
            self.win_nav_sub.addItem(ns[0])
        self.win_nav.currentIndexChanged.connect(self.on_win_nav_changed)
        
        self.win_combo = ComboBox()
        self.update_win_combo()
        self.recognize_btn = PushButton('RE')
        self.recognize_btn.clicked.connect(lambda checked=False: self.onclick_recogize())
        
        self.loc_ocr_te = QTextEdit(self)
        self.loc_ocr_te.setPlaceholderText("auto ocr")
        self.loc_ocr_te.setReadOnly(True)
        self.loc_ocr_te.setMaximumHeight(60)
        
        self.kw_le = LineEdit()
        self.kw_le.setPlaceholderText("输入关键字")
        self.kw_le.returnPressed.connect(self.onclick_search)
        self.search_btn = PushButton('Search')
        self.search_btn.clicked.connect(lambda checked=False: self.onclick_search())
        
        self.qa_lw = ListWidget(self)
        self.qa_lw.setMinimumHeight(350)  
        self.label_qa = [QALabel() for i in range(c.DT_QA_LIST_NUM)]
        li_height = 80
        for i in range(c.DT_QA_LIST_NUM):
            listItem = QListWidgetItem(self.qa_lw)
            # self.label_qa[i].label_q.setText(f"{i}")
            self.label_qa[i].setMaximumHeight(li_height)
            qsize = QSize(400, li_height)
            listItem.setSizeHint(qsize)
            self.qa_lw.setItemWidget(listItem, self.label_qa[i])
            
        self.tips_label = CaptionLabel('')
        self.setTips(c.TIPS_OCR)
        
        self.vBoxLayout = QVBoxLayout(self)
        self.vBoxLayout_alert= QVBoxLayout()
        self.hBoxLayout_nav = QHBoxLayout()
        self.hBoxLayout_re = QHBoxLayout()
        self.hBoxLayout_ocr = QHBoxLayout()
        self.hBoxLayout_search = QHBoxLayout()
        self.vBoxLayout_qa = QVBoxLayout()
        
        self.initLayout()

    def initLayout(self):
        
        self.vBoxLayout_alert.setSpacing(10)
        self.vBoxLayout_alert.setContentsMargins(5, 5, 3, 3)
        self.vBoxLayout_alert.addWidget(self.alert_lb)
        
        self.hBoxLayout_nav.setSpacing(10)
        self.hBoxLayout_nav.setContentsMargins(5, 5, 3, 3)
        self.hBoxLayout_nav.addWidget(self.win_nav)
        self.hBoxLayout_nav.addWidget(self.win_nav_sub)
        
        self.hBoxLayout_re.setSpacing(10)
        self.hBoxLayout_re.setContentsMargins(5, 5, 3, 3)
        self.hBoxLayout_re.addWidget(self.win_combo, 4)
        self.hBoxLayout_re.addWidget(self.recognize_btn, 1)
        
        self.hBoxLayout_ocr.setSpacing(10)
        self.hBoxLayout_ocr.setContentsMargins(5, 5, 3, 3)
        self.hBoxLayout_ocr.addWidget(self.loc_ocr_te)
        
        self.hBoxLayout_search.setSpacing(10)
        self.hBoxLayout_search.setContentsMargins(5, 5, 3, 5)
        self.hBoxLayout_search.addWidget(self.kw_le, 4)
        self.hBoxLayout_search.addWidget(self.search_btn, 1)
        
        self.vBoxLayout_qa.setSpacing(10)
        self.vBoxLayout_qa.setContentsMargins(5, 5, 3, 5)
        self.vBoxLayout_qa.addWidget(self.qa_lw, 4)
        self.vBoxLayout_qa.addWidget(self.tips_label, 1)
        
        self.vBoxLayout.addLayout(self.vBoxLayout_alert)
        self.vBoxLayout.addLayout(self.hBoxLayout_nav)
        self.vBoxLayout.addLayout(self.hBoxLayout_re)
        self.vBoxLayout.addLayout(self.hBoxLayout_ocr)
        self.vBoxLayout.addLayout(self.hBoxLayout_search)
        self.vBoxLayout.addLayout(self.vBoxLayout_qa)
        
    def on_win_nav_changed(self, index):
        # logger.info("Selected:", index)
        self.win_nav_sub.clear()
        for ns in dt_nav[index][1]:
            self.win_nav_sub.addItem(ns[0])
            
    def update_win_combo(self):
        self.win_combo.clear()
        hwnd_title.clear()
        win32gui.EnumWindows(get_all_hwnd, 0)
        for h, t in hwnd_title.items():
            if t.startswith('梦幻西游 ONLINE'):
                self.win_combo.addItem(str(h)+":"+t)
                
    def clear_qalist(self) :
        self.qa_lw.scrollToTop()
        for i in range(c.DT_QA_LIST_NUM):
            self.label_qa[i].clear() 
            
    def setTips(self, tips):
        self.tips_label.setText(f"<font color='red'>{tips}</font>")
        
    def show_developmode(self):
        # 计算主窗口中心位置
        main_window_center = self.father.main_window.LocateCenter()
        print(f"main window location: {main_window_center}")
        x = main_window_center.x() - c.win_width / 2 + 20
        y = main_window_center.y() - 250
        p = QPoint(x, y)
        self.sf_developmode.move(p)
        self.sf_developmode.show()
        
    @logger.catch
    def onclick_search(self, checked=False) :
        if c.URL_QA == "":
            self.setTips("请先设置后台 ip 和 port")
            return
        
        self.setTips("")
        n = self.win_nav.currentIndex()
        nsub = self.win_nav_sub.currentIndex()
        id = dt_nav[n][1][nsub][1]
        logger.info(f"{n}-{nsub} id: {id}")
        
        kw = self.kw_le.text()
        if kw == "":
            msg = "请输入查询关键字！"
            logger.warning(msg)
            self.setTips(msg) 
            return
        logger.info(f"{n} {nsub} {id} {kw}")
        qs, ok = maocr.search(id, kw)
        if not ok:
            msg = "查找失败"
            logger.warning(msg)
            self.setTips(msg) 
            return
        
        
        c.annc_server = qs[1]
        c.annc_sponsor = qs[2]
        self.clear_qalist()
        if qs[0] == None:
            msg = "查找失败"
            self.setTips(msg) 
            logger.warning(msg)
            return
        for i, q in enumerate(qs[0]):
            logger.info(f"{i} {q}")
            self.label_qa[i].setText(q)
                
    @logger.catch
    def onclick_recogize(self):
        if c.URL_QA == "":
            self.setTips("请先设置后台 ip 和 port")
            return
        
        self.setTips("")
        if not u.signin_flag:
            msg = "仅登录用户可用"
            self.setTips(msg)
            logger.warning(msg) 
            return
        
        win_text = self.win_combo.currentText()
        if win_text == "":
            msg = "没有可用窗口"
            logger.warning(msg)
            self.setTips(msg) 
            self.update_win_combo()
            return
        h = win_text.split(':')[0]
        t = win_text.split(':')[1]
        logger.info(f"{h} {t}")
        
        if not win32gui.IsWindowEnabled(h):
            msg = "无效窗口, 请重新选择窗口！"
            logger.warning(msg)
            self.setTips(msg) 
            self.update_win_combo()
            return
        
        n = self.win_nav.currentIndex()
        nsub = self.win_nav_sub.currentIndex()
        qa_type = dt_nav[n][1][nsub][0]
        id = dt_nav[n][1][nsub][1]
        ri = dt_nav[n][1][nsub][2]
        logger.info(f"{n}-{nsub}  qa type: {qa_type} id: {id} ri: {ri}")
            
        # img_hwnd = get_screenshot_image(int(h))
        img_hwnd = get_mss_screenshot_image(int(h))
        # opencv_image = cv2.imread(os.path.join(c.shot_dir_path, r'q3.png'))
        # if opencv_image is None:
        #     self.setTips("文件查找失败，避免中文路径") 
        #     return
        # rgb_image = cv2.cvtColor(opencv_image, cv2.COLOR_BGR2RGB)
        # img_hwnd = Image.fromarray(rgb_image)
        logger.info(f"shot size {img_hwnd.size}")
        ts = time_str()
        if c.develop_mode:
            self.setTips("开发者模式，用于图片截取校准，正常使用请退出该模式！")
            file_img = f"{c.shot_dir_path}/dm_{h}_{ts}.jpg"
            img_hwnd.save(file_img)
            logger.info(f'img_desktop save to -> {os.path.abspath(file_img)}')
            # self.sf_developmode.UpdateImage("D:\workspace\mhxyQA_GUI\images\shot\g1.jpg", c.qa_shot_rect[ri])
            self.sf_developmode.UpdateImage(file_img, c.qa_shot_rect_default[ri])
            self.sf_developmode.SetTitle(f"{qa_type}截图校准")
            self.sf_developmode.SetIndex(ri)
            self.show_developmode()
            return
        
        crop_box = (c.qa_shot_rect[ri][0], c.qa_shot_rect[ri][1], c.qa_shot_rect[ri][2], c.qa_shot_rect[ri][3])
        img_hwnd = img_hwnd.crop(crop_box)
        
        file_img = f"{c.shot_dir_path}/{h}_{t}_{ts}.png"
        img_hwnd.save(file_img, 'PNG')
        logger.info(f'img_desktop save to -> {os.path.abspath(file_img)}')
        ok = True
        re, ok = maocr.recognize(id, file_img, u.signin_token)
        if not ok:
            msg = "识别失败"
            logger.warning(msg)
            self.setTips(msg) 
            return
        text = re[0]
        res = re[1]
        ocrleftcount = re[2]
        message = re[3]
        c.annc_server = re[4]
        c.annc_sponsor = re[5]
        
        if message != "":
            self.setTips(message)
        
        # logger.info(text)
        # logger.info(res)
        self.recognize_btn.setText(f"RE({ocrleftcount})")
        delete_file(file_img)
        if text == "":
            self.setTips("识别失败")
            return
            
        if ok:
            self.loc_ocr_te.setText(text)
            sorted_list = sorted(res, key=lambda x: custom_sort(x['Q'], text))
            self.clear_qalist()
            for i, q in enumerate(sorted_list):
                if i > 4:
                    break
                logger.info(f"{i}: {q}")
                self.label_qa[i].setText(q)


class QAInterface(SingleDirectionScrollArea):

    def __init__(self, parent=None):
        super().__init__(parent=None)

        self.view = QWidget(self)
        self.main_window = parent

        self.vBoxLayout = QVBoxLayout(self.view)
        self.qaCard = QaInfoCard(self)
        self.qaCard.setMaximumWidth(c.card_width)
        self.setWidget(self.view)
        self.setWidgetResizable(True)
        self.setObjectName('QAInterface')

        self.vBoxLayout.setSpacing(10)
        self.vBoxLayout.setContentsMargins(0, 0, 5, 0)
        self.vBoxLayout.addWidget(self.qaCard, 0, Qt.AlignTop)

        self.setStyleSheet("QScrollArea {border: none; background:transparent}")
        self.view.setStyleSheet('QWidget {background:transparent}')
        
    def show(self):
        print("show QAInterface")
        
        